// Note that if a problem occurs, memory is not properly freed. I find it too much of a bother to unload the resources which have already been loaded.
CSpinner::CSpinner (short inAcurID)
{
SAcurPtr theAcurPtr;
short theIndex;
CursHandle theCursor;
ThrowIfResFail_(mAcurHandle = (SAcurHandle) ::GetResource ('acur', inAcurID)); // Get the main resource
::DetachResource((Handle) mAcurHandle); // Detach it because we will modify its contents
::HLock ((Handle) mAcurHandle); // Lock it down before dereferencing it
theAcurPtr = *mAcurHandle;
for (theIndex = 0; theIndex < theAcurPtr->itsFrameCount; theIndex++) { // Walk the frame list
ThrowIfResFail_(theCursor = (CursHandle) ::GetCursor(HiWord(theAcurPtr->itsFrame[theIndex]))); // At first each entry contains the ID of a 'CURS' resource
::HLock((Handle) theCursor); // Which we now load and lock
theAcurPtr->itsFrame[theIndex] = theCursor; // And write into the entry
}
mTickInterval = theAcurPtr->itsCurrentFrame; // Read the tick interval from the 'acur' resource
mTaskInstalled = false;
}
// If the destructor is called because an exception has been raised, the user probably hasn't been able to call Stop. We'll do that for him.
// We release mAcurHandle. We do not release the 'CURS' resources, though. This isn't a leak since the next calls to GetCursor will retrieve the same copies of the cursors.
// This routine assumes that the address of the VBLTask structure is the same as the address of the CSpinner object. This hack allows us not to mess with A5 at all.
VBLTASKPROTOTYPE
{
CSpinner *theSpinner;
register SAcurPtr theAcurPtr;
theSpinner = (CSpinner*) inTaskPtr; // Retrieve the address of the CSpinner object (skanky hack)
theAcurPtr = *theSpinner->mAcurHandle; // Retrieve the address of the SAcurRec structure
::SetCursor(*theAcurPtr->itsFrame[theAcurPtr->itsCurrentFrame++]); // Set the cursor to the next frame
if (theAcurPtr->itsCurrentFrame == theAcurPtr->itsFrameCount) // If the last frame was just used, cycle
theAcurPtr->itsCurrentFrame = 0;
inTaskPtr->vblCount = theSpinner->mTickInterval; // Reset the VBL task